/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package serversocket;
import java.util.ArrayList;
/**
 *
 * @author Antonio
 */
public class Operacion extends Thread
{
    String mensaje;
    ArrayList<Sucursal> lista;
   

    public Operacion(String mensaje) {
        this.mensaje = mensaje;
    }    

    /**
     * Dependiendo del digito contenido en la primera casilla del 
     * arreglo del mensaje, se determina que accion realizar
     */
    private void decodificarpaquete()
    {
       int tipo = Integer.parseInt(obtenerDatoMensaje()[0]);
       switch (tipo)
       {
       case 0:
          configuracion();
          break;
       case 1:
          llegoCamion();
          break;
       case 2:
          salioCamion();
           break;
       case 3:
         cargarSucursal(obtenerDatoMensaje()[1],Integer.parseInt(obtenerDatoMensaje()[2]));
            break;
       default:
               System.out.println("ha ocurrido un error");
       }
    }



    private void cargarSucursal(String ip, int puerto)
    {
        String respuesta="3%";
      //int a =  ListaSucursal.getListSucursal().obtener().size();       
         ArrayList <Sucursal> listSucursal = ListaSucursal.getListSucursal().obtener();

         String nodos= "";

        for (int i = 0; i< listSucursal.size() ; i++)
        {
            nodos = nodos +listSucursal.get(i).getIdSucursal()+"%";

            System.out.println("ciclo "+ i + " " + listSucursal.get(i).getIdSucursal());
        }
            System.out.println("nodos "+ nodos);
        respuesta = respuesta+ (nodos);
        System.out.println("lo que te envio: "+respuesta);


       EnviarMensaje enviar =  new EnviarMensaje(ip,puerto,respuesta);

        enviar.start();
    }
    
    /**
     * Metodo encargado organizar la estructura del anillo
     * recibe como entrada, el mensaje de configuracion inicial del nodo
     * nuevo y le responde con los puertos de sus nodos vecinos
     */
    private void configuracion()
    {
        /**
         * Mensaje decodificado separado en las casillas del arreglo
         */
        String [] Datos = obtenerDatoMensaje();
        /**
         * Indica la posicion que ocupa dentro del arreglo la sucursal
         * que esta siendo añadida al anillo
         */
        int indice;
        /**
         * Se cargan los datos de la sucursal contenidos en el mensaje
         * recibido
         */
        Sucursal sucursal = new Sucursal(Datos[1], Integer.parseInt(Datos[4]),
                                         Integer.parseInt(Datos[5]), Integer.parseInt(Datos[3]), Datos[2]);
        /**
         * Se agrega la sucursal nueva a la lista de sucursales del servidor
         */
        ListaSucursal.getListSucursal().agregar(sucursal);
        /**
         * Dependiendo de la cantidad de nodos del anillo (longitud de la lista
         * de sucursales) se ejecuta una logica determinada para la 
         * agregacion 
         */
        
        /**
         * 1er caso: La lista solo contiene un nodo,el nodo que acaba de
         * solicitar ingresar al anillo.
         */
        if(ListaSucursal.getListSucursal().obtener().size() == 1 )
        {
           System.out.println("Soy nodo 0");
           /**
            * Se calcula el indice que le corresponde al nodo que acaba de 
            * ingresar, deberia ser 0
            */
           indice = ListaSucursal.getListSucursal().obtener().size()-1;
           /**
            * Se contruye el mensaje de respuesta que el servidor envia 
            * a la sucursal
            */
           String respuesta = "0%"+indice +"%0%0";
           /**
            * Se construye el paquete con los datos a enviar a la sucursal
            * @params ListaSucursal.getListSucursal().obtener().get(0).getIp() = 
            * direccion ip de la sucursal que se va a añadir al anillo
            * @params  ListaSucursal.getListSucursal().obtener().get(0).getPortEscuchaC() = 
            * Puerto de la sucursal dedicado a escuchar al servidor central
            * @params respuesta = mensaje con la informacion de la configuracion
            * que le asigna el servidor central a la nueva sucursal
            */
           EnviarMensaje enviarPrimero =  new EnviarMensaje(ListaSucursal.getListSucursal().obtener().get(0).getIp(),
                                       ListaSucursal.getListSucursal().obtener().get(0).getPortEscuchaC(),
                                       respuesta);
           /**
            * Se crea un hilo dedicado a enviar el mensaje con la nueva
            * configuracion a la sucursal entrante
            */
           enviarPrimero.start();
           /**
            * Se asigna el indice dentro del arreglo a la nueva sucursal
            */
           ListaSucursal.getListSucursal().obtener().get(0).setIdSucursal(indice);
        }
        /**
         * 2do caso: La lista solo contiene 2 nodos, el segundo es el nodo
         * que acaba de solicitar ser añadido al anillo
         */
        if(ListaSucursal.getListSucursal().obtener().size() == 2)
        {
           System.out.println("Soy nodo 1");
           /**
            * Se actualizan los puertos del nodo 0 (primer nodo en la lista)
            * enviando los puertos de su vecino nodo 1 (nodo entrante)
            */
           
           /**
            * Puerto de salida antihorario
            */
           ListaSucursal.getListSucursal().obtener().get(0).setPortSalidaA(
                    ListaSucursal.getListSucursal().obtener().get(1).getPortEscuchaA());
           
           /**
            * Puerto de salida horario
            */
           ListaSucursal.getListSucursal().obtener().get(0).setPortSalidaH(
                    ListaSucursal.getListSucursal().obtener().get(1).getPortEscuchaH());
           /**
            * Se asignan los puertos de salida del nodo 1 (nodo entrante)
            * enviando los puertos de su vecino nodo 0 (primer nodo en la lista)
            */
           /**
            * Puerto de salida antihorario
            */
           ListaSucursal.getListSucursal().obtener().get(1).setPortSalidaA(
                    ListaSucursal.getListSucursal().obtener().get(0).getPortEscuchaA());
           /**
            * Puerto de salida horario
            */
           ListaSucursal.getListSucursal().obtener().get(1).setPortSalidaH(
                    ListaSucursal.getListSucursal().obtener().get(0).getPortEscuchaH());
           /**
            * Se calcula el indice que le corresponde al primer nodo del anillo 
            * para actualizar sus datos
            */
           indice = ListaSucursal.getListSucursal().obtener().size()-2;
           /**
            * Se construye el paquete con los nuevos de la sucursal 0 (primera del anillo)
            * @params ListaSucursal.getListSucursal().obtener().get(0).getIp() = 
            * direccion ip de la sucursal que se va a añadir al anillo
            * @params  ListaSucursal.getListSucursal().obtener().get(0).getPortEscuchaC() = 
            * Puerto de la sucursal dedicado a escuchar al servidor central
            * @params respuesta = mensaje con la informacion de la nueva configuracion
            * que le asigna el servidor central a la primera sucursal
            */
           EnviarMensaje enviarPrimero =  new EnviarMensaje(ListaSucursal.getListSucursal().obtener().get(0).getIp(),
                                                   ListaSucursal.getListSucursal().obtener().get(0).getPortEscuchaC(),
                                                   "0%" + indice+ "%"+ ListaSucursal.getListSucursal().obtener().get(0).getPortSalidaH() + "%" +
                                                   + ListaSucursal.getListSucursal().obtener().get(0).getPortSalidaA());
           
           
           ListaSucursal.getListSucursal().obtener().get(indice).setIdSucursal(indice);//Esta sentencia es innecesaria ya el nodo tiene este dato
           /**
            * Se crea un hilo dedicado a enviar el mensaje con la nueva
            * configuracion a la sucursal 0 del anillo
            */
           enviarPrimero.start();
            /**
            * Se calcula el indice que le corresponde al primer nodo que acaba
            * de entrar
            */
           indice = ListaSucursal.getListSucursal().obtener().size()-1;
           /**
            * Se construye el paquete con los nuevos de la sucursal 0 (primera del anillo)
            * @params ListaSucursal.getListSucursal().obtener().get(indice).getIp() = 
            * direccion ip de la sucursal que se va a añadir al anillo
            * @params  ListaSucursal.getListSucursal().obtener().get(indice).getPortEscuchaC() = 
            * Puerto de la sucursal dedicado a escuchar al servidor central
            * @params respuesta = mensaje con la informacion de la nueva configuracion
            * que le asigna el servidor central a la primera sucursal
            */
           EnviarMensaje enviarUltimo =  new EnviarMensaje(ListaSucursal.getListSucursal().obtener().get(indice).getIp(),
                                                   ListaSucursal.getListSucursal().obtener().get(indice).getPortEscuchaC(),
                                                   "0%" + indice+ "%"+  ListaSucursal.getListSucursal().obtener().get(indice).getPortSalidaH()
                                                   + "%" + ListaSucursal.getListSucursal().obtener().get(indice).getPortSalidaA());
           /**
            * Se asigna el indice dentro del arreglo a la nueva sucursal
            */
           ListaSucursal.getListSucursal().obtener().get(indice).setIdSucursal(indice);
           /**
            * Se crea un hilo dedicado a enviar el mensaje con la nueva
            * configuracion a la sucursal 1 del anillo
            */
           enviarUltimo.start();
        }
        /**
         * 3er caso: La lista solo contiene mas 2 nodos, el nuevo es el nodo
         * que acaba de solicitar ser añadido al anillo
         */
        if(ListaSucursal.getListSucursal().obtener().size() > 2)
        {
            ListaSucursal.getListSucursal().obtener().get(0).setPortSalidaA(
            ListaSucursal.getListSucursal().obtener().get(ListaSucursal.getListSucursal().obtener().size()-1).getPortEscuchaA());

            ListaSucursal.getListSucursal().obtener().get(ListaSucursal.getListSucursal().obtener().size()-2).setPortSalidaH(
            ListaSucursal.getListSucursal().obtener().get(ListaSucursal.getListSucursal().obtener().size()-1).getPortEscuchaH());

            ListaSucursal.getListSucursal().obtener().get(ListaSucursal.getListSucursal().obtener().size()-1).setPortSalidaA(
            ListaSucursal.getListSucursal().obtener().get(ListaSucursal.getListSucursal().obtener().size()-2).getPortEscuchaA());

            ListaSucursal.getListSucursal().obtener().get(ListaSucursal.getListSucursal().obtener().size()-1).setPortSalidaH(
            ListaSucursal.getListSucursal().obtener().get(0).getPortEscuchaH());
            System.out.println("Soy nodo nuevo");
            indice = 0;
            EnviarMensaje enviarPrimero =  new EnviarMensaje(ListaSucursal.getListSucursal().obtener().get(0).getIp(),
                                                   ListaSucursal.getListSucursal().obtener().get(0).getPortEscuchaC(),
                                                   "0%" + indice+ "%"+ ListaSucursal.getListSucursal().obtener().get(0).getPortSalidaH() + "%" +
                                                   + ListaSucursal.getListSucursal().obtener().get(0).getPortSalidaA());

            ListaSucursal.getListSucursal().obtener().get(indice).setIdSucursal(indice);
            enviarPrimero.start();
            int indicePenultimo = ListaSucursal.getListSucursal().obtener().size()-2;
            EnviarMensaje enviarPenultimo =  new EnviarMensaje(ListaSucursal.getListSucursal().obtener().get(indicePenultimo).getIp(),
                                                   ListaSucursal.getListSucursal().obtener().get(indicePenultimo).getPortEscuchaC(),
                                                   "0%" + indicePenultimo+ "%"+  ListaSucursal.getListSucursal().obtener().get(indicePenultimo).getPortSalidaH()
                                                   + "%" + ListaSucursal.getListSucursal().obtener().get(indicePenultimo).getPortSalidaA());

            ListaSucursal.getListSucursal().obtener().get(indicePenultimo).setIdSucursal(indicePenultimo);
            enviarPenultimo.start();

            int indiceUltimo = ListaSucursal.getListSucursal().obtener().size()-1;
            EnviarMensaje enviarUltimo =  new EnviarMensaje(ListaSucursal.getListSucursal().obtener().get(indiceUltimo).getIp(),
                                                   ListaSucursal.getListSucursal().obtener().get(indiceUltimo).getPortEscuchaC(),
                                                   "0%" + indiceUltimo+ "%"+  ListaSucursal.getListSucursal().obtener().get(indiceUltimo).getPortSalidaH()
                                                   + "%" + ListaSucursal.getListSucursal().obtener().get(indiceUltimo).getPortSalidaA());
            ListaSucursal.getListSucursal().obtener().get(indiceUltimo).setIdSucursal(indiceUltimo);
            enviarUltimo.start();
        }
        ListaSucursal.getListSucursal().imprimirTodo();
    }

    /**
     * Decodifica los datos del mensaje
     * asignando un dato por casilla segun el separador
     * "%"
     * @return Datos del mensaje descodificado
     */
    
    private String []  obtenerDatoMensaje()
    {
         String [] respuesta = new String[30];
         respuesta = mensaje.split("%");
         return respuesta;
    }


    private void llegoCamion()
    {
        //Responder Sucursal
        String [] datos = obtenerDatoMensaje();
        EnviarMensaje mensaje = new EnviarMensaje(ListaSucursal.getListSucursal().obtener().get(Integer.parseInt(datos[1])).getIp(),
                                ListaSucursal.getListSucursal().obtener().get(Integer.parseInt(datos[1])).getPortEscuchaC(),
                                MainServer.notificacion.revisarCamion(this.mensaje));
        mensaje.start();
    }

    private void salioCamion()
    {
        MainServer.notificacion.revisarSalidaCamion(mensaje);
    }
    
    @Override
    public void run()
    {
        decodificarpaquete();
    }
}






